Skip to content

Agent skills install from the npm packages the project already has - #219

Merged
wmadden merged 88 commits into
mainfrom
claude/agent-skills-npm-packages-770857
Aug 24, 2026
Merged

Agent skills install from the npm packages the project already has#219
wmadden merged 88 commits into
mainfrom
claude/agent-skills-npm-packages-770857

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

In a project that has @prisma/orm-postgres installed, this now works — no network, no extra tooling:

$ prisma skills sync
Synced 1 skill.
  project  /work/my-app
  check    enabled

  Skill      Package               Version   Installed into
  prisma-8   @prisma/orm-postgres  8.1.0     .claude/skills, .cursor/skills, .agents/skills, .windsurf/skills

And after pnpm up @prisma/orm-postgres bumps the package but nobody re-runs sync, every prisma command appends one line to stderr:

Prisma agent skills are out of date (installed @prisma/orm-postgres 8.1.0, synced 8.0.0). Run: prisma skills sync

Base: main, rebased onto #218's squash merge (3a8f7d2) on 2026-08-22; the branch carries only this PR's own commits.

The decision

Agent skills now travel inside the npm packages they describe, and this PR adds the CLI half of that: prisma skills sync copies them into place, prisma skills list reports status, prisma init sets a project up once, and a staleness notice after every command keeps the copies from silently rotting.

An agent skill is a directory with a SKILL.md — instructions that teach a coding agent (Claude Code, Cursor, Codex, Windsurf) how to use a library. Each harness auto-indexes skills from a known project directory (.claude/skills/, .cursor/skills/, .agents/skills/, .windsurf/skills/); a skill anywhere else is invisible. So a skill is only useful if something copies it into those directories and keeps the copy matching the installed package version. Until now that something was prisma orm init shelling out to a third-party CLI that cloned our skills from GitHub at a ref named after the package version — a convention, not a guarantee — and nothing ever detected that the copies had gone stale.

How sync decides what to install

Sync resolves a hardcoded allowlist of four packages — @prisma/orm-postgres, @prisma/orm-sqlite, @prisma/orm-mongo, @prisma/composer — by name from the project root and each workspace member directory. It never scans node_modules: a skill is instructions an agent will follow, so a scanner would let any transitive dependency inject instructions into the agent. That invariant is stated (and marked permanent) at the allowlist declaration, and this PR's trust boundary is exactly the code's — the only skills installed come from packages the user deliberately installed.

Each shipped SKILL.md carries a version stamp in its frontmatter, under the Agent Skills spec's metadata map (custom top-level keys are not spec-defined):

metadata:
  library: "@prisma/orm-postgres"
  library_version: "8.1.0"

Sync compares the installed package's version against the stamp in each harness copy and re-copies on mismatch. Pruning removes only copies whose stamp names an allowlisted package that is no longer installed — a skill some other tool put there is never touched. The synced copies are ordinary files git tracks; sync removes the * ignore file an earlier revision wrote into its copies, but leaves any .gitignore a user authored in place. If two workspace members pin different versions of one package, the highest wins and sync warns. Yarn PnP works because all reads go through Node's resolution and fs layers (there is a test that fakes the PnP zip filesystem to prove it).

Sync refuses what it does not own. A target directory whose SKILL.md is unstamped, unreadable, or stamped by a non-allowlisted package — a hand-written skill colliding on name — is left byte-for-byte intact, reported in a refused array and a SKILLS.UNMANAGED_DIRECTORY diagnostic, and the summary line never claims "up to date" without naming it. A directory whose SKILL.md is genuinely absent (an interrupted copy) is repaired.

prisma init

prisma init initializes a repository for Prisma development, purely locally — no platform calls. Two steps, each with an opt-out (--no-postinstall, --no-skills), always exit 0, never prompts, idempotent:

  1. Adds "postinstall": "prisma skills sync || exit 0" to the current directory's package.json, so skills resync on every install and upgrade. A different existing postinstall script is never clobbered or chained — init reports it and tells the user what to append. BOM, CRLF, indentation, and trailing-newline style are preserved; an unreadable, unwritable, or malformed manifest is a diagnostic, not a failure.
  2. Runs the skills sync in-process at the discovered workspace root. A sync failure is a diagnostic on a successful init.

This is a new command reusing a retired name: #218 deleted the old compute-config wizard, and nothing from it returns. Sync itself still never touches package.json (a test pins byte-identity across a sync run) — writing the hook is exclusively the act of a user running init.

The prisma agent group is deleted

prisma agent install|update|status — the old installer that shelled out to npx skills@latest for the v6/v7 skills — is gone (operator ruling, 2026-08-21). The post-login tip that advertised it now offers prisma skills sync instead, only when installed packages actually have stale copies, and can no longer fail a login that already succeeded.

The staleness notice

It prints to stderr, after the command's own output, never changes the exit code, and is deliberately not TTY-dependent — its main reader is an agent running the CLI without one. Off switches: --quiet, --json / --format json, --version, PRISMA_SKILLS_CHECK=0, CI/GITHUB_ACTIONS, skills: { check: false } in prisma.config.ts (an explicit --config <path> is honored), a persistent opt-out written by prisma skills sync --disable (stored in .prisma/skills.json), and any skills command itself. Flag scanning stops at a bare --. The per-command cost is stat calls and small file reads; prisma.config.ts is only evaluated after staleness is already established. With the init-written postinstall as the primary trigger, the notice is the backstop for projects that never ran init or removed the script.

Pin and state dir find the project root

.prisma/local.json (the link pin) and the state dir are now discovered by walking up from the cwd to the nearest directory containing .prisma/ — a pure filesystem check, no config file is read — so a repo linked at its root works from apps/api/. Nearest wins deliberately: a subdirectory linked to a different project beats the root. Commands that rewrite or delete the pin operate on the file they found, not on the cwd. When no .prisma/ exists, behavior is unchanged.

The rename: CLI_NAME is now prisma

The published package (prisma) has installed a bin named prisma since 8.0.0-rc.3, but every string the CLI printed still said prisma-cli. This PR moves CLI_NAME, so help text, error guidance, and the notice above all name the binary users actually have. There is no compatibility layer: the CLI is pre-rc and owes old spellings nothing, so every producer of error guidance was fixed to emit the current commands directly, and the display-time rewriter that used to patch up legacy spellings (renameAppCopy and friends) was deleted rather than extended. fromLegacyCliError survives only as a structural converter (legacy error shape → CliError); it no longer rewrites or filters any copy. Deliberate survivals, so nobody "finishes" the rename by mistake: the @prisma/cli package's own bin and README, the update-check entrypoint matcher and cache directory, git@github.com:prisma/prisma-cli.git repo URLs, and the utm_source/utm_campaign sign-in tags.

Tests

90+ new tests: npm/pnpm/Yarn-PnP fixture projects, every sync/check state (stale, never-synced, in-sync, refused, opted out), the collision and unreadable-skill refusals (chmod-based), pruning on package removal, a two-member monorepo with the version-conflict warning, every off switch, init's full package.json edge-case matrix (foreign script, non-object scripts, BOM, CRLF, read-only file, missing manifest), a credential-free e2e driving the built binary through init twice, a readdir-count regression test bounding workspace-glob expansion, and the legacy-error mapper suite.

For other owners

  • The feedback client's user-agent changed from prisma-cli/<version> to prisma/<version> — wire-visible; whoever reads that dashboard should know.
  • isLikelyGlobalNpmEntrypoint (update-check) still matches only prisma-cli install paths, so a globally installed prisma gets the docs-link fallback instead of a concrete update command. Pre-existing, untouched here, newly conspicuous.
  • The browser login success page still shows a static npx skills add prisma/skills copy button — the last surface promoting the retired installer; its removal is pending an operator decision.
  • Init stops touching agent skills; the family-level prisma init owns skills setup prisma#30097 (orm init) drops its scaffold-time sync call per operator ruling — follow-up on that PR.

Merge order: #218 is merged; this PR next, then prisma/prisma#30096 (packaging) → #30097, and prisma/composer#251's npm release — all ship skills only this CLI can read.

Alternatives considered

  • Keep fetching from GitHub via npx skills add (status quo): version matched by ref-name convention only, unmanaged copies, network access during init, and an unpinned third-party CLI in our init path.
  • Discover skills by scanning node_modules: prompt-injection by construction — any transitive dependency could plant instructions. Permanently rejected.
  • Symlinks into node_modules instead of copies: no node_modules under Yarn PnP, symlink creation needs elevation on Windows, and only Claude Code documents following symlinked skills. Version-stamped, checked, auto-resynced copies are a managed cache.
  • A line in AGENTS.md telling agents to run sync each session: rejected by the team — agents shouldn't carry maintenance duties.
  • A postinstall in our own packages: dependency lifecycle scripts are blocked by default in pnpm 10+, bun, and Deno. Permanently rejected.
  • Writing a postinstall from prisma orm init or from sync itself (the original design): rejected — a routine command silently editing your package.json, or re-adding a script you removed, is not acceptable. The operator's final ruling: the hook is written only by prisma init, a command whose whole point the user invokes deliberately; nothing automatic ever edits the manifest, and the staleness notice covers everyone else.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 122 files, which is 22 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e872ce3a-049a-483f-ac23-77669cde8eb4

📥 Commits

Reviewing files that changed from the base of the PR and between b02432d and 90d7789.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (122)
  • .drive/projects/prisma-cli-v8/deferred.md
  • .drive/projects/prisma-cli-v8/specs/config-file-resolution.md
  • biome.jsonc
  • docs/architecture/overview.md
  • docs/product/cli-style-guide.md
  • docs/product/command-principles.md
  • docs/product/error-conventions.md
  • docs/product/output-conventions.md
  • packages/cli-conformance/src/checks/tarball.ts
  • packages/cli-conformance/tests/tarball.test.ts
  • packages/cli/AGENTS.md
  • packages/cli/e2e/agent.e2e.ts
  • packages/cli/e2e/declared-bin.e2e.ts
  • packages/cli/e2e/init.e2e.ts
  • packages/cli/package.json
  • packages/cli/scripts/conformance.ts
  • packages/cli/src/adapters/local-state.ts
  • packages/cli/src/cli-command.ts
  • packages/cli/src/cli-name.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/agent/errors.ts
  • packages/cli/src/commands/agent/install.ts
  • packages/cli/src/commands/agent/presentation.ts
  • packages/cli/src/commands/agent/results.ts
  • packages/cli/src/commands/agent/skills-cli.ts
  • packages/cli/src/commands/agent/status.ts
  • packages/cli/src/commands/agent/update.ts
  • packages/cli/src/commands/auth/agent-setup-tip.ts
  • packages/cli/src/commands/bucket/key-create.ts
  • packages/cli/src/commands/bucket/key-delete.ts
  • packages/cli/src/commands/bucket/key-list.ts
  • packages/cli/src/commands/init.ts
  • packages/cli/src/commands/project/create.ts
  • packages/cli/src/commands/project/env-add.ts
  • packages/cli/src/commands/project/env-delete.ts
  • packages/cli/src/commands/project/env-shared.ts
  • packages/cli/src/commands/project/env-update.ts
  • packages/cli/src/commands/project/errors.ts
  • packages/cli/src/commands/project/link.ts
  • packages/cli/src/commands/project/show.ts
  • packages/cli/src/commands/service/errors.ts
  • packages/cli/src/commands/skills/config.ts
  • packages/cli/src/commands/skills/family.ts
  • packages/cli/src/commands/skills/list.ts
  • packages/cli/src/commands/skills/presentation.ts
  • packages/cli/src/commands/skills/results.ts
  • packages/cli/src/commands/skills/sync.ts
  • packages/cli/src/controllers/app-env-file.ts
  • packages/cli/src/controllers/app-env.ts
  • packages/cli/src/controllers/database.ts
  • packages/cli/src/controllers/project.ts
  • packages/cli/src/errors.ts
  • packages/cli/src/lib/agent/constants.ts
  • packages/cli/src/lib/agent/setup-status.ts
  • packages/cli/src/lib/app/domain-guidance.ts
  • packages/cli/src/lib/app/env-config.ts
  • packages/cli/src/lib/app/env-file.ts
  • packages/cli/src/lib/bucket/provider.ts
  • packages/cli/src/lib/database/provider.ts
  • packages/cli/src/lib/project/local-pin.ts
  • packages/cli/src/lib/project/prisma-dir.ts
  • packages/cli/src/lib/project/resolution.ts
  • packages/cli/src/lib/project/setup.ts
  • packages/cli/src/lib/semver-order.ts
  • packages/cli/src/lib/skills/allowlist.ts
  • packages/cli/src/lib/skills/frontmatter.ts
  • packages/cli/src/lib/skills/opt-out.ts
  • packages/cli/src/lib/skills/resolve.ts
  • packages/cli/src/lib/skills/status.ts
  • packages/cli/src/lib/skills/sync.ts
  • packages/cli/src/lib/skills/unquote.ts
  • packages/cli/src/lib/skills/workspace-members.ts
  • packages/cli/src/lib/version.ts
  • packages/cli/src/main.ts
  • packages/cli/src/skills-check.ts
  • packages/cli/src/state-dir.ts
  • packages/cli/src/types/auth.ts
  • packages/cli/src/update-check.ts
  • packages/cli/tests/agent-setup-tip.test.ts
  • packages/cli/tests/agent.test.ts
  • packages/cli/tests/auth.test.ts
  • packages/cli/tests/branch.test.ts
  • packages/cli/tests/bucket.test.ts
  • packages/cli/tests/e2e-coverage.test.ts
  • packages/cli/tests/feedback.test.ts
  • packages/cli/tests/git.test.ts
  • packages/cli/tests/golden-rendering.test.ts
  • packages/cli/tests/helpers/skills-fixture.ts
  • packages/cli/tests/init.test.ts
  • packages/cli/tests/mount-coverage.test.ts
  • packages/cli/tests/postgres.test.ts
  • packages/cli/tests/prisma-dir-anchor.test.ts
  • packages/cli/tests/project.test.ts
  • packages/cli/tests/service-create.test.ts
  • packages/cli/tests/service-delete.test.ts
  • packages/cli/tests/service-domain-wait.test.ts
  • packages/cli/tests/service-domain.test.ts
  • packages/cli/tests/service-list.test.ts
  • packages/cli/tests/service-logs.test.ts
  • packages/cli/tests/service-open.test.ts
  • packages/cli/tests/service-session.test.ts
  • packages/cli/tests/service-show.test.ts
  • packages/cli/tests/service-version-delete.test.ts
  • packages/cli/tests/service-version-list.test.ts
  • packages/cli/tests/service-version-promote.test.ts
  • packages/cli/tests/service-version-rollback.test.ts
  • packages/cli/tests/service-version-show.test.ts
  • packages/cli/tests/service-version-start.test.ts
  • packages/cli/tests/service-version-stop.test.ts
  • packages/cli/tests/skills-check.test.ts
  • packages/cli/tests/skills-pnp.test.ts
  • packages/cli/tests/skills-project.test.ts
  • packages/cli/tests/skills-sync.test.ts
  • packages/cli/tests/telemetry.test.ts
  • packages/cli/tests/update-check-wiring.test.ts
  • packages/cli/tests/v8-conformance.test.ts
  • packages/cli/tests/whoami.test.ts
  • packages/prisma/package.json
  • packages/prisma/src/config.ts
  • packages/prisma/tests/config.test.ts
  • packages/prisma/tsdown.config.ts
  • scripts/output-gallery/build.mjs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Aug 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@prisma/cli@219
npx https://pkg.pr.new/@prisma/cli-engine@219

commit: d5a8d45

@wmadden-electric
wmadden-electric marked this pull request as ready for review August 21, 2026 11:00
@wmadden-electric wmadden-electric changed the title Add prisma skills sync/list and the skill staleness check Agent skills install from the npm packages the project already has Aug 21, 2026
@wmadden-electric
wmadden-electric force-pushed the claude/agent-skills-npm-packages-770857 branch from 8842b4c to 4350bb3 Compare August 21, 2026 15:32
@wmadden-electric
wmadden-electric changed the base branch from main to claude/kind-jennings-32a0e4 August 21, 2026 15:32
Base automatically changed from claude/kind-jennings-32a0e4 to main August 22, 2026 11:39
@wmadden-electric
wmadden-electric force-pushed the claude/agent-skills-npm-packages-770857 branch from 575a441 to 8e1b0a6 Compare August 22, 2026 11:44
Adds `prisma skills sync` and `prisma skills list`, and the staleness
check every other command runs.

Skills now travel inside the Prisma packages a project installs, so a
copy in a harness skill directory is current only when its
`library_version` stamp matches the version of the package it came
from. Sync resolves the allowlisted packages by name from the project
root and from each declared workspace member, copies each skill tree
into the four harness directories, and removes copies whose source
package is gone. It never scans node_modules — the allowlist states why
that is permanent.

The check lives in main.ts after dispatch: every mounted family runs
through that one call, so the ORM and Composer families need no copy of
it. It writes one stderr line, never changes the exit code, and is
silenced by --quiet, --json/--format json, PRISMA_SKILLS_CHECK=0, CI,
`skills: { check: false }` in prisma.config.ts, and
`skills sync --disable`.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Fixture projects in the layouts npm and pnpm produce, a workspace with
two members pinning different versions, and a Yarn PnP fixture that
patches Node's resolver and the filesystem module the way .pnp.cjs
does — so the tests fail if the sync ever builds a node_modules path
itself or reads through an API the PnP layer does not patch.

Covers every state a copy can be in (in sync, stale, never synced,
orphaned), pruning on package removal, leaving skills from other
packages alone, exit 0 whenever there is nothing to do, and each of the
check's off switches.

The fixtures clear NODE_PATH first: vitest points it at this
repository's pnpm store, which would otherwise make every fixture
project look like it had two allowlisted packages installed.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The staleness notice is not TTY-gated, which the update-notification
section would otherwise imply is the rule for advisory stderr lines, so
its own section says why and lists every way to silence it.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`prisma --config <path> skills list` invokes the command that fixes
stale skills, so the check must recognise the group even when shared
flags come first. Also trims sync's help to the two examples the style
guide asks for.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A `packages/**` workspace made member enumeration walk the whole
working tree — dist, coverage, .git, every source directory — and the
resolver was then pointed at each one, four package names at a time.
The staleness check runs that on every command, so an ordinary
workspace pattern cost roughly a second per invocation instead of the
milliseconds the design budgets.

The walk now stops at a directory holding a package.json, because that
directory is the member and everything below it is the package's own
contents, and it never enters a dot-directory. Only directories with a
package.json are returned, so `**` answers with packages rather than
with directories.

The new test counts directory reads rather than timing them: on a
workspace with two built members it reads `packages` and
`packages/group` and nothing else.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`skills sync` printed `check: enabled` in a project whose
prisma.config.ts sets `skills: { check: false }`, contradicting
`skills list` and the check itself. It now needs the same config
section and combines it with the persisted opt-out the same way.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The Agent Skills spec defines no custom top-level frontmatter keys;
extensions live under `metadata`, a map of strings. Slices 1 and 4 are
stamping `metadata.library` and `metadata.library_version`, so the
reader follows them there and nowhere else. No fallback to the old
top-level spelling: nothing has shipped one, and accepting both would
let a skill claim a stamp the spec has no place for.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Operator decision: the published binary is `prisma`, so CLI_NAME — the
one place the user-facing name lives — now says `prisma`, and every
command string, notice, error next step, help line and sample output
follows it. `prisma-cli` survives only where it names something that
really is still called that: the `@prisma/cli` package's own bin (its
README and the update check's entrypoint detection), the update-check
cache directory, the repository URL, the sign-in campaign tag, and the
legacy error copy the service group rewrites.

That rewriting is why one behavioural change came with the rename:
`fromLegacyCliError` turned a legacy `nextSteps` line into a
run-command action only when it began `prisma-cli `, and dropped every
other line. Legacy builders written with the new spelling would have
lost their next steps, so the mapper now recognises both spellings and
renames `<name> app ` to `<name> service ` either way.

The feedback client's user-agent follows CLI_NAME too, so it now
reports `prisma/<version>`; it identifies this binary, and this binary
is called prisma.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`/docs/orm/tools/prisma-cli` is the path that 308-redirects to the ORM
CLI reference, which is the whole reason the comment cites it. The
sweep matched it because the path was followed by a space, and
output-conventions.md kept the right spelling, so the two disagreed.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The mapper's current-spelling branch does have a producer —
`computeConfigErrorToCliError` writes `prisma service <command>` into
nextSteps, and `resolveComputeManagementContext` maps it — so removing
the branch fails two tests in service-compute-config. What it lacked
was a test that says so directly: those two fail for reasons that read
as compute-config behaviour.

These drive `renameAppCopy` and `fromLegacyCliError` with one spelling
each, and pin the asymmetry that makes this worth covering — a command
line the mapper does not recognise is dropped from nextActions rather
than passed through, so an unrecognised spelling costs the user their
next step with nothing to show for it.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Round-4 review fixes (S2-R3-1, S2-R3-2), committed at session halt;
suites not re-run. Includes drive project artifacts up to this point.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The branch's only cli-engine change was two doc-comment lines renamed in a prisma-cli -> prisma sweep. That trips the engine-version check because 0.2.0 is already published, and publishing the engine for comments is not worth it. Restore the file to origin/main byte-for-byte.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Both failures were in test fixtures, not production code — the skills library joins every path with path.join, which is correct on Windows.

skills-pnp: the fake PnP layer remapped virtual paths with a startsWith check against a forward-slash prefix, but on Windows path.join hands it backslash paths, so the remap missed and sync found no packages. The fixture now compares in forward-slash form.

skills-workspace-scan: the recorded readdir paths carry native separators, so the expected relative paths did not match on Windows. The assertion now normalizes separators before comparing; the set of directories it pins is unchanged.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…eout flake

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
User prisma.config.ts files import definePrismaConfig from prisma/config; the entry re-exports it from @prisma/cli-engine, which stays external, and ships its own types. @manypkg/tools comes in for the workspace enumeration rework.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
skills.agents in prisma.config.ts names which agent harnesses get skill copies; the default is every known agent (claude, cursor, agents, devin — windsurf is gone, its product renamed to Devin Desktop which reads .devin/skills). findProjectRoot is deleted: sync, list, the staleness notice, the post-login tip and the opt-out file all read from the directory the command runs in. The notice stays cheap: it reads the full agent set first and evaluates the config at most once, only when that already looks stale and only when a config file exists.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The hand-written pnpm-workspace.yaml line parser and glob matcher go. PnpmTool and YarnTool read the declared globs from plain files (pnpm-workspace.yaml, package.json workspaces in both forms) and expand them with node_modules excluded, which covers npm, pnpm, bun and Yarn PnP alike and keeps the trust boundary: membership comes only from what the user declared, never from scanning installed packages.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A fresh project gets a config with skills.agents spelled out; an existing prisma.config.ts is never edited — init reports the exact snippet to add instead. --skills takes the comma-separated agent list that both the scaffold and this run's sync use, or 'none' to skip the skills steps; --no-skills is gone.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The temp project gets a node_modules/prisma symlink to the built package, so the scaffold's prisma/config import resolves exactly as in a user install, and the file init wrote is evaluated by the same loadConfig every command uses, asserting zero diagnostics. The rerun test removes the config first: the built binary cannot currently evaluate any prisma.config.ts in this repository's development layout (a defect that predates this work, reproduced at commit 7532706 with a dependency-free config; the c12 import inside the engine resolves through the pnpm symlink and misses its store siblings). The config-exists rerun stays covered in the unit suite.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
output-conventions and command-principles describe the agents map, the default set, init's scaffold and the never-edit rule; the prisma package declares @manypkg/tools so its bundle keeps the dependency external like its other runtime deps.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…file text

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…figs

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…project's config

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…requires

packages/prisma pinned @prisma/orm-toolchain 8.0.0-rc.4 and
@prisma/composer-cli 0.11.0 while bundling @prisma/cli source that
requires rc.5 / 0.12.0. A command definition imported from rc.4 comes
back undefined and the engine crashes with 'Cannot read properties of
undefined (reading needs)' on every invocation, --version included.
The skew is pre-existing on main. Align the pins with packages/cli.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
When the c12 specifier resolves through a pnpm symlink that is never
realpath'd (the dev workspace layout, and pnpm installs with
hoist=false), c12's own 'import "pathe"' walks up from the symlink
path, where its store siblings are unreachable, and every config
evaluation fails with CLI.CONFIG_UNREADABLE: Cannot find package
'pathe'. Import c12 through the realpath of its resolved URL instead.
A resolution failure still throws inside evaluateConfigFile, so it
still surfaces as the unreadable-config diagnostic.

The import-purity conformance check now excuses c12 from the
reverse (unimported-dependency) half: import.meta.resolve is not an
import, which is the exact case allowedUnimported exists for.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The rerun no longer deletes prisma.config.ts before invoking the
built binary: with c12 imported through its realpath the binary can
evaluate the config in this repository's layout, so the test now
asserts the honest behavior — a second init with the config present
reports the config step as exists and exits 0.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
An engine change forces a version bump, and the published families peer-pin the engine exactly, so shipping it means a coordinated family release. The defect only affects this repo's dev layout and pnpm hoist=false installs — npm and default pnpm installs evaluate configs fine — so it waits for the next engine train. The verified one-line fix (import c12 through its realpath) is recorded in the e2e comment and the ledger.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric
wmadden-electric force-pushed the claude/agent-skills-npm-packages-770857 branch from 857bed4 to 85beca3 Compare August 24, 2026 12:25
…oes quiet

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden
wmadden merged commit 14c0ec8 into main Aug 24, 2026
13 checks passed
@wmadden
wmadden deleted the claude/agent-skills-npm-packages-770857 branch August 24, 2026 12:55
birhantprkc pushed a commit to birhantprkc/prisma that referenced this pull request Aug 24, 2026
…30096)

The prisma-8 skill now ships inside the npm tarballs users actually
install, instead of being fetched from GitHub by `npx skills add` at
init time.

## What changed

- **The two upgrade skills fold into the `prisma-8` router.**
`prisma-next-upgrade` and `prisma-8-extension-upgrade` become an
"upgrading" branch of `skills/prisma-8/` (per-transition
`upgrades/<from>-to-<to>/` layout kept), their trigger phrases move into
the router's `description`, and the router opens with a preamble telling
the agent the installed version's skill is the source of truth. Three
registered skills become one.
- **Version stamp under `metadata`.** The skill frontmatter carries
`metadata.library` (the npm package name) and
`metadata.library_version`, stamped by the version pipeline
(`scripts/set-version.ts`) so the stamp and the package version cannot
diverge. The keys live under the Agent Skills spec's `metadata` map — a
string→string extension point — rather than as undefined top-level keys.
- **The skill travels in three tarballs.** `skills/prisma-8/` is staged
into `@prisma/orm-postgres`, `@prisma/orm-sqlite`, and
`@prisma/orm-mongo` at `prepack` time, with `"skills"` in each package's
`files`. Each copy's `metadata.library` names the package it ships in.
- **The packaging is proved from the artifact, not the working tree.**
The publish-surface test deletes the staged tree, runs `pnpm pack` the
way the publish workflow does, reads the stamped `SKILL.md` back out of
the tarball, and byte-compares every file against the tracked source. It
fails if the `files` entry or the `prepack` script is removed.
- **The upgrade-coverage check follows the fold.** `USER_SKILL_PKG` /
`EXT_SKILL_PKG` point at the folded directories and the path regex is
derived from them.
- Docs updated: `skills/README.md` (authoring rules for the stamp, the
GitHub route demoted to a manual fallback), `docs/oss/versioning.md`,
`docs/reference/error-reference.md`.

## What consumes this

`prisma skills sync` in prisma/prisma-cli
([prisma/prisma-cli#219](prisma/prisma-cli#219))
copies these skills from the installed packages into the agent harness
directories and reads the `metadata` stamp to detect staleness. The init
wiring that runs sync lands separately, stacked on this branch.

Merge order: prisma/prisma-cli#219 ships first (it owns the `prisma
skills` command), then this, then the init wiring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Prisma ORM packages now bundle a version-matched `prisma-8` skill for
application and extension upgrades.
* Added upgrade guidance and migration tools covering historical Prisma
version transitions.
* Skills now synchronize automatically during package initialization and
packaging.

* **Documentation**
* Updated installation, synchronization, versioning, error-handling, and
authoring guidance.

* **Bug Fixes**
  * Improved skill metadata validation and version stamping.
* Retired legacy standalone upgrade skill references and installation
paths.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
birhantprkc pushed a commit to birhantprkc/prisma that referenced this pull request Aug 24, 2026
…kills setup (prisma#30097)

`prisma orm init` stops delivering agent skills entirely. The old GitHub
fetch (`npx skills add`) is removed, and init does not run `prisma
skills sync` either: skills setup belongs to the family-level `prisma
init` command that ships in
[prisma/prisma-cli#219](prisma/prisma-cli#219).

> Operator ruling (Will Madden, 2026-08-21): `prisma orm init` must not
run `skills sync` at scaffold time — the family-level `prisma init` owns
skills setup. An earlier revision of this branch ran the sync once at
scaffold time with a `--skip-skills` opt-out; both are removed.

Stacked on prisma#30096 (the tarball packaging). Retarget to `main` after
prisma#30096 merges.

## What changed

- **Init runs no skills command at all.** `DEFAULT_SKILL_SOURCES`'
GitHub invocations are gone and nothing replaced them: no `skills add`,
no `skills sync`, no postinstall script, no skill gitignore entries. The
`--skip-skills` flag is removed with the behavior it opted out of.
Init's next-steps list carries one pointer: run `prisma init` in the
project to set up the agent skills. The integration test asserts init
spawns no skills command and fetches nothing from GitHub.
- **One binary everywhere.** The CLI dev dependency is `prisma@next` —
the package that actually carries the `prisma` bin — and every string
init writes or runs uses it: the engine-version probe, the emit spawn,
the `contract:emit` script, next-actions, and the scaffold
quick-reference. The integration test asserts one binary end to end.
- **The skill-install failure path is retired.** Exit code 6 and
`skillInstallFailedFinding` are removed; `error-reference.md` updated.
- **Retired skill directories are still cleaned up.** Init keeps
deleting the pre-`prisma-8` skill directories it finds in the agent
harness roots.

## Notes for reviewers

- Existing projects are untouched: they keep `@prisma/cli` and
`prisma-cli` scripts, which still work. Whether to ship a migration
entry for them is a product decision left open deliberately.
- The repo-wide `prisma-cli` → `prisma` string rename (~10 `fix:`
strings, root README) is deliberately not part of this change and needs
its own owner.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- `prisma orm init` now focuses on project setup and no longer installs
or synchronizes agent skills.
- Run `prisma init` to configure skills, or `prisma skills sync` to
refresh them.
  - Contract emission now uses the project’s local `prisma` command.

- **Documentation**
- Updated setup guidance, examples, error references, and quick
references to use the current `prisma orm init` and `prisma` command
syntax.
  - Removed obsolete skill-installation options and instructions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants